package org.CrossApp.lib;

import java.lang.reflect.Method;
import java.net.URI;
import java.nio.ByteBuffer;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.net.http.SslError;
import android.util.Log;
import android.view.Gravity;
import android.view.KeyEvent;
import android.widget.FrameLayout;
import android.widget.Toast;

import com.tencent.smtt.export.external.interfaces.SslErrorHandler;
import com.tencent.smtt.sdk.ValueCallback;
import com.tencent.smtt.sdk.WebChromeClient;
import com.tencent.smtt.sdk.WebChromeClient.FileChooserParams;
import com.tencent.smtt.sdk.WebSettings;
import com.tencent.smtt.sdk.WebSettings.LayoutAlgorithm;
import com.tencent.smtt.sdk.WebView;
import com.tencent.smtt.sdk.WebViewClient;

@SuppressLint("SetJavaScriptEnabled")
public class CrossAppWebView extends WebView {
	
	private static final String TAG = CrossAppWebViewHelper.class.getSimpleName();
	private int viewTag;
	private String jsScheme;
	private String szWebViewRect;

	public CrossAppWebView(Context context) {
		this(context, -1);
	}

	public CrossAppWebView(Context context, int viewTag) {
		super(context);
		this.viewTag = viewTag;
		this.jsScheme = "";
		this.szWebViewRect = "0-0-0-0";
		// 可以使html表单能够接收键盘输入
		this.requestFocus();
		this.setFocusable(true);
		this.setDrawingCacheEnabled(true);
		this.setFocusableInTouchMode(true);
		this.addJavascriptInterface(new InJavaScriptLocalObj(), "local_obj");
		WebSettings settings = this.getSettings();
		// 缩放至屏幕的大小
		settings.setLoadWithOverviewMode(true);
		// 不保存表单数据
		settings.setSaveFormData(false);
		// 关闭webview中缓存
		settings.setCacheMode(WebSettings.LOAD_NO_CACHE);
		// 不可缩放
		settings.setSupportZoom(false);
		settings.setBuiltInZoomControls(false);
		// 隐藏原生的缩放控件
		settings.setDisplayZoomControls(false);
		// 自适应屏幕
		settings.setUseWideViewPort(true);
		// 保存密码
		settings.setSavePassword(false);
		// 获取地理位置
		settings.setGeolocationEnabled(false);
		// 允许使用LocalStorage
		settings.setDomStorageEnabled(true);
		// 启用JS
		settings.setJavaScriptEnabled(true);
		// 排版适应屏幕
		settings.setLayoutAlgorithm(LayoutAlgorithm.NARROW_COLUMNS);
		// 是否支持多个窗口
		settings.setSupportMultipleWindows(true);
		// 允许访问文件
		settings.setUseWideViewPort(true);
		settings.setAllowFileAccess(true);
		// 支持经过JS打开新窗口
		settings.setJavaScriptCanOpenWindowsAutomatically(true);
		// 支持自动加载图片
		settings.setLoadsImagesAutomatically(true);
		// 设置编码格式
		settings.setDefaultTextEncodingName("UTF-8");
		// `searchBoxJavaBridge_` has big security risk.
		// http://jvn.jp/en/jp/JVN53768697
		try {
			Method method = this.getClass().getMethod("removeJavascriptInterface", new Class[] { String.class });
			method.invoke(this, "searchBoxJavaBridge_");
		} catch (Exception e) {
			Log.e(TAG, "This API level do not support `removeJavascriptInterface`");
		}
		this.setWebViewClient(new CrossAppWebViewClient());
		this.setWebChromeClient(new MyWebChromeClient());
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if (keyCode == KeyEvent.KEYCODE_BACK) {
			return CrossAppGLSurfaceView.getInstance().onKeyDown(keyCode, event);
		}
		
		return super.onKeyDown(keyCode, event);
	}

	public void setJavascriptInterfaceScheme(String scheme) {
		this.jsScheme = scheme != null ? scheme : "";
	}

	public void setScalesPageToFit(boolean scalesPageToFit) {
		this.getSettings().setSupportZoom(scalesPageToFit);
	}

	private Bitmap bmp;
	private ByteBuffer imageData;

	private static native void onSetByteArrayBuffer(int index, byte[] buf, int wdith, int height);

	public void getWebViewImage() {
		bmp = this.getDrawingCache();
		if (bmp != null && imageData == null) {
			imageData = ByteBuffer.allocate(bmp.getRowBytes() * bmp.getHeight());
			bmp.copyPixelsToBuffer(imageData);
			CrossAppActivity.getContext().runOnGLThread(new Runnable() {
				@Override
				public void run() {
					onSetByteArrayBuffer(viewTag, imageData.array(), bmp.getWidth(), bmp.getHeight());
					imageData = null;
				}
			});
		}
	}

	class CrossAppWebViewClient extends WebViewClient {
		
		@Override
		public boolean shouldOverrideUrlLoading(WebView view, final String urlString) {
			if (urlString.startsWith("weixin://wap/pay?")) {
				try {
					Intent intent = new Intent();
					intent.setAction(Intent.ACTION_VIEW);
					intent.setData(Uri.parse(urlString));
					CrossAppActivity.getContext().startActivity(intent);
				} catch (Exception exception) {
					Toast.makeText(CrossAppActivity.getContext(), "支付失败,请重试", Toast.LENGTH_SHORT).show();
				}
				CrossAppActivity.getContext().runOnGLThread(new Runnable() {
					@Override
					public void run() {
						CrossAppWebViewHelper._onJsCallback(viewTag, urlString);
					}
				});
				
				return true;
			} else if (urlString.contains("platformapi/startapp")) {
				try {
					Intent intent = new Intent();
					intent.setAction(Intent.ACTION_VIEW);
					intent.setData(Uri.parse(urlString));
					intent.addCategory("android.intent.category.BROWSABLE");
					intent.setComponent(null);
					CrossAppActivity.getContext().startActivity(intent);
				} catch (Exception exception) {
					Toast.makeText(CrossAppActivity.getContext(), "支付失败,请重试", Toast.LENGTH_SHORT).show();
				}
				CrossAppActivity.getContext().runOnGLThread(new Runnable() {
					@Override
					public void run() {
						CrossAppWebViewHelper._onJsCallback(viewTag, urlString);
					}
				});
				
				return true;
			}
			URI uri = URI.create(urlString);
			if (uri != null && uri.getScheme().equals(jsScheme)) {
				CrossAppActivity.getContext().runOnGLThread(new Runnable() {
					@Override
					public void run() {
						CrossAppWebViewHelper._onJsCallback(viewTag, urlString);
					}
				});
				return true;
			}
			
			return CrossAppWebViewHelper._shouldStartLoading(viewTag, urlString);
		}

		@Override
		public void onPageFinished(WebView view, final String url) {
			super.onPageFinished(view, url);
			CrossAppActivity.getContext().runOnGLThread(new Runnable() {
				@Override
				public void run() {
					CrossAppWebViewHelper._didFinishLoading(viewTag, url);
				}
			});
		}

		@Override
		public void onReceivedError(WebView view, int errorCode, String description, final String failingUrl) {
			super.onReceivedError(view, errorCode, description, failingUrl);
			CrossAppActivity.getContext().runOnGLThread(new Runnable() {
				@Override
				public void run() {
					CrossAppWebViewHelper._didFailLoading(viewTag, failingUrl);
				}
			});
		}

		public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
			handler.proceed();
		}
		
	}

	final class InJavaScriptLocalObj {
		public void showSource(String html) {
			CrossAppWebViewHelper.didLoadHtmlSource(html);
			CrossAppWebViewHelper.s_bWaitGetHemlSource = false;
		}
	}

	public void setWebViewRect(int left, int top, int maxWidth, int maxHeight) {
		fixSize(left, top, maxWidth, maxHeight);
		this.szWebViewRect = String.format("%d-%d-%d-%d", left, top, maxWidth, maxHeight);
	}

	public String getWebViewRectString() {
		return szWebViewRect;
	}

	public int getViewTag() {
		return viewTag;
	}

	private void fixSize(int left, int top, int width, int height) {
		FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);
		layoutParams.gravity = Gravity.LEFT | Gravity.TOP;
		layoutParams.leftMargin = left;
		layoutParams.topMargin = top;
		layoutParams.width = width;
		layoutParams.height = height;
		this.setLayoutParams(layoutParams);
	}

	public class MyWebChromeClient extends WebChromeClient {

		// Android 3.0 以下
		public void openFileChooser(ValueCallback<Uri> valueCallback) {
			CrossAppActivity.getContext().getOnValueCallbackListenner().OnValueCallback(valueCallback);
		}

		// Android 3~4.1
		public void openFileChooser(ValueCallback<Uri> valueCallback, String acceptType) {
			CrossAppActivity.getContext().getOnValueCallbackListenner().OnValueCallback(valueCallback, acceptType);
		}

		// Android 4.1以上
		public void openFileChooser(ValueCallback<Uri> valueCallback, String acceptType, String capture) {
			CrossAppActivity.getContext().getOnValueCallbackListenner().OnValueCallback(valueCallback, acceptType, capture);
		}

		// Android 5.0以上
		@Override
		public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
			CrossAppActivity.getContext().getOnValueCallbackListenner().OnValueCallback(webView, filePathCallback, fileChooserParams);
			return true;
		}
		
	}

	public interface OnValueCallbackListenner {
		
		void OnValueCallback(ValueCallback<Uri> valueCallback);

		void OnValueCallback(ValueCallback<Uri> valueCallback, String acceptType);

		void OnValueCallback(ValueCallback<Uri> valueCallback, String acceptType, String capture);

		void OnValueCallback(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams);

	}

}